def splitPattern(pattern):
    pi = 0;
    pl = len(pattern);
    lets = [];
    pats = [];
    wilds = [];
    for pi in range(0, pl):
        pat = pattern[pi];
        if pat == '*':
            if len(lets) == 0:
                continue;
            last_p = lets.pop();
            if len(lets) != 0:
                pats.append(''.join(lets));
                wilds.append(False);
                lets.clear();

            lets.append(last_p);
            lets.append(pat);
            pats.append(''.join(lets));
            wilds.append(True);
            lets.clear();
        elif pat == '.':
            if len(lets) == 1 and lets[0] == '.':
                pats.append(lets[0]);
                wilds.append(True);
            elif len(lets) > 0:
                pats.append(''.join(lets));
                wilds.append(False);
            lets.clear();
            lets.append(pat);
        else:
            if len(lets) == 1 and lets[0] == '.':
                pats.append(lets[0]);
                wilds.append(True);
                lets.clear();
            lets.append(pat);
    if len(lets) != 0:
        pats.append(''.join(lets));
        if lets.count('.') > 0 or lets.count('#') > 0:
            wilds.append(True);
        else:
            wilds.append(False);
    print(pats, wilds);
    return pats, wilds;

def wildMatch(string, pats):
    points = pats.count('.');
    if points == len(string):
        return True;
    elif points > len(string):
        return False;

    pi = 0;
    for let in string:
        if pats[pi] == '.':
            pi += 1;
        elif let == pats[pi][0] or pats[pi][0] == '.':
            continue;
        else:
            pi += 1;
            while pi < len(pats):
                if pats[pi] == '.':
                    pi += 1;
                    break;
                elif let == pats[pi][0]:
                    break;

            if pi == len(pats):
                return False;
    return True;

def match(s, pattern):
    """

    . match one single char
    * match zero or more of the preceding element
    The matching should cover the entire input string

    :type s: str
    :type pattern: str
    :rtype: True or False

    Maybe with issues, not cover all conditions
    """

    if len(s) == 0:
        print('Please input something');
        return True;
    elif len(pattern) == 0:
        print('Pattern cannot be empty');
        return False;
        
    if pattern.startswith('*'):
        print('Invalid pattern');
        return False;

    print(s);
    p_fragments, wilds = splitPattern(pattern);

    #match each fragment
    s_list = [];
    index = 0;
    for i in range(0, len(p_fragments)):
        fragment = p_fragments[i];

        if not wilds[i]:
            cnt = s.count(fragment, index);
            if cnt == 0:
                return False;

            start = index;
            l = [];
            while cnt != 0 and start < len(s):
                start = s.index(fragment, start);
                l.append(start);
                start += 1;
                cnt = s.count(fragment, start);
            s_list.append(l);
            index = s_list[i][0] + len(fragment);
            if i > 0 and p_fragments[i - 1] == '.':
                s_list[i - 1][0] = s_list[i][0] - 1;
        else:
            l = [];
            if fragment == '.':
                l.append(index);
                index += 1;
            elif fragment[0] == '.':
                l.append(index);
            else:
                cnt = s.count(fragment[0], index);
                if cnt != 0:
                    start = s.index(fragment[0], index);
                    l.append(start);
                    if i > 0 and p_fragments[i - 1] == '.':
                        s_list[i - 1][0] = start - 1;
                else:
                    l.append(index);
            s_list.append(l);
    print(s_list);

    #find the match sequence
    start = 0; # index in str
    wild_start = 0; # index in p_fragments
    for j in range(0, len(s_list)):
        s_item = s_list[j];
        fragment = p_fragments[j];

        if not wilds[j]:
            match = False;
            if j == 0: # first item
                if s_item[0] > 0:
                    return False;
                else:
                    first = s_item[0];
                    s_item.clear();
                    s_item.append(first);
            elif j == len(s_list) - 1: # last item
                last = s_item.pop();
                s_item.clear();
                s_item.append(last);
                if s_item[0] + len(fragment) != len(s):
                    return False;

            for k in range(0, len(s_item)):
                match = wildMatch(s[start:s_item[k]], p_fragments[wild_start:j]);
                if match:
                    start = s_item[k] + len(fragment);
                    if j == len(s_list) - 1:
                        if start == len(s):
                            break;
                        else:
                            match = False;
                    else:
                        if s_list[j + 1].count(start) > 0:
                            for item in s_list[j + 1]:
                                if item < start:
                                    s_list[j + 1].remove(item);
                                else:
                                    break;
                            break;
                        else:
                            match = False;

            if not match:
                return False;
            wild_start = j + 1;
        else:
            if j == len(s_list) - 1: # last item
                match = wildMatch(s[start:], p_fragments[wild_start:j+1]);
                if not match:
                    return False;
                
    return True;
